package com.fita.tencent.handle.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.http.annotation.Rao;
import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.wechat.entity.cfg.Config;
import com.demo2do.core.wechat.rao.wechat.WeappAuthRao;
import com.demo2do.core.wechat.utils.WechatUtils;
import com.fita.tencent.entity.weappauth.WeappAuth;
import com.fita.tencent.handle.WeappAuthHandler;
import com.fita.tencent.utils.AESUtils;

/**
 * 
 * @author wangliwang
 *
 */
@Service("weappAuthHandler")
public class WeappAuthHandlerImpl implements WeappAuthHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(WeappAuthHandlerImpl.class);
    
    private Config config;
    
    @Rao
    private WeappAuthRao weappAuthRao;
    
    /**
     * 
     * @param appid
     * @param appsecret
     */
    @Autowired
    public void config(@Value("#{weapp['appid']}") String appid, @Value("#{weapp['appsecret']}") String appsecret) {
        this.config = new Config(appid, appsecret);
    }

    /* (non-Javadoc)
     * @see com.fita.appserver.handler.AuthenticationHandler#authenticate(java.lang.String)
     */
    public Map<String, Object> authenticate(String code) {
        
        try {
            
            // construct request parameters
            Map<String, Object> parameters = new HashMap<String, Object>();
            parameters.put("appid", config.getAppid());
            parameters.put("secret", config.getAppsecret());
            parameters.put("js_code", code);
            parameters.put("grant_type", "authorization_code");
            
            // execute remote request
            HttpResult httpResult = weappAuthRao.requestOpenid(parameters);
            
            // check result is valid
            if(WechatUtils.isValid(httpResult)) {
                // get response data
                Map<String, Object> response = httpResult.describe();
                return response;
            }
            
            logger.error("#authenticate() - response data [{}] is invalid", httpResult.getResponseText());
            throw WechatUtils.toBusinessException(httpResult);
            
        } catch (Exception e) {
            logger.error("#authenticate() - call wechat get openid occurs a exception [{}]", e);
            throw BusinessException.newInstance("500", "获取openid失败");
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.fita.appserver.handler.AuthenticationHandler#decrypt(java.lang.String, java.lang.String, java.lang.String)
     */
    public WeappAuth decrypt(String encryptedData, String sessionKey, String iv) {
        
        try {
            
            WeappAuth weappAuth = null;
            
            logger.info("#decrypt - start call AES#decrypt with encryptedData[{}] sessionKey[{}] iv[{}]", encryptedData, sessionKey, iv);
            
            byte[] content = Base64.decodeBase64(encryptedData);
            byte[] keyByte = Base64.decodeBase64(sessionKey);
            byte[] ivByte = Base64.decodeBase64(iv);
            logger.info("#decrypt - start call AES#decrypt with content[{}] key[{}] iv[{}]", content, keyByte, ivByte);
            
            byte[] original = AESUtils.decrypt(content, keyByte, ivByte);
            
            if (ArrayUtils.isNotEmpty(original) && original.length > 0) {
                String decryptString = new String(original, "UTF-8");
                weappAuth = JsonUtils.parse(decryptString, WeappAuth.class);
            }
            
            if(weappAuth == null) {
                logger.error("#decrypt - get empty decryptData");
                throw BusinessException.newInstance("501", "解密失败");
            }
            
            if(!weappAuth.isValid() && !weappAuth.matches(config.getAppid())) {
                logger.error("#decrypt - not valid decryptData [{}] or decryptData's appid not match setting's appid[{}]", JsonUtils.toJson(weappAuth), config.getAppid());
                throw BusinessException.newInstance("502", "解密失败，参数错误");
            }
            
            logger.info("#decrypt [{}]", JsonUtils.toJson(weappAuth));
            
            return weappAuth;
            
        } catch(Exception e) {
            logger.error("#decrypt - AES#decrypt faild", e);
            throw BusinessException.newInstance("501", "解密失败");
        }
    }

}
